#include <assert.h>

#include "../src/parse.h"

static char*
random_worker_string (void)
{
  unsigned int len = 1.0 + 10.0 * drand48 ();
  char buf[1 + len];

  for (unsigned int n = 0; n < len; ++n)
    {
      do
        {
          buf[n] = lrand48 ();
        }
      while (! isgraph (buf[n]) || buf[n] == ':');
    }
  buf[len] = '\0';

  return strdup (buf);
}

static void
random_nonpipe (char*        tag,
                unsigned int len)
{
  for (unsigned int n = 0; n < len; ++n)
    {
      do
        {
          tag[n] = lrand48 () % 256;
        }
      while (! isgraph (tag[n]) || tag[n] == '|');
    }
}

static void
test_parse_once (void)
{
  FILE* f = tmpfile ();
  unsigned int n_labels = 1.0 + 50.0 * drand48 ();
  unsigned int n_workers = 1.0 + 50.0 * drand48 ();
  unsigned int n_ratings = 1.0 + 50.0 * drand48 ();
  int clamp = (drand48 () < 0.5) ? -1 : n_labels * drand48 ();
  Rating ratings[n_ratings];
  unsigned int n_tag = 0.0 + 50.0 * drand48 ();
  char tag[n_tag + 1];

  random_nonpipe (tag, n_tag);
  tag[n_tag] = '\0';

  if (clamp >= 0)
    {
      fprintf (f, "%d %s|", clamp, tag);
    }
  else
    {
      fprintf (f, " %s|", tag);
    }

  for (unsigned int n = 0; n < n_ratings; ++n)
    {
      unsigned int label = n_labels * drand48 ();
      ratings[n].rating = label;

      if (drand48 () < 0.5)
        {
          unsigned int worker = lrand48 ();
          ratings[n].worker = worker % n_workers;

          fprintf (f, " %u:%u", worker, label);
        }
      else
        {
          char* worker = random_worker_string ();
          ratings[n].worker = hash (worker) % n_workers;

          fprintf (f, " %s:%u", worker, label);

          free (worker);
        }
    }

  fprintf (f, "\n");

  fseek (f, SEEK_SET, 0);

  Rating the_ratings[n_ratings];
  char the_tag[1024];
  int the_clamp = -1;
  int rv = parse_ratings (f,
                          the_ratings,
                          n_ratings + 3.0 * drand48 (),
                          the_tag,
                          sizeof (the_tag),
                          &the_clamp,
                          69,
                          n_labels,
                          n_workers);

  assert (rv == (int) n_ratings);
  assert (strcmp (tag, the_tag) == 0);
  assert (memcmp (ratings, the_ratings, n_ratings * sizeof (ratings[0])) == 0);
  assert (clamp == the_clamp);

  fclose (f);
}

static void
test_parse (void)
{
  for (unsigned int i = 0; i < 100; ++i)
    {
      test_parse_once ();
    }
}

int 
main (void) 
{
  srand48 (69);

  test_parse ();

  return 0;
}
